<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可连接的矩形</title>
    <script src="js/api.js"></script>
    <script src="js/vue.min.js"></script>
    <script src="js/axios.min.js"></script>
    <script src="js/util.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 20px;
        }

        #canvas {
            width: 1000px;
            height: 600px;
            border: 1px solid #ccc;
            position: relative;
            background-color: #f9f9f9;
            overflow: hidden;
        }

        .connection-point {
            width: 10px;
            height: 10px;
            background-color: #e74c3c;
            border-radius: 50%;
            position: absolute;
            cursor: pointer;
        }


        svg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .controls {
            margin: 10px 0;
        }

        button {
            padding: 8px 15px;
            background-color: #2ecc71;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        button:hover {
            background-color: #27ae60;
        }

        .rectangle {
            position: absolute;
            width: 200px;
            height: 100px;
            border: 1px solid black;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

            background-color: #3498db;
            border-radius: 5px;
            cursor: move;
            user-select: none;
        }

        .input-box, .dropdown {
            margin: 5px;
            width: 80%; /* 根据实际需求调整宽度 */
        }

        .left-points, .right-points {
            position: absolute;
            top: 0;
            bottom: 0;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
        }

        .left-points {
            left: 0;
        }

        .right-points {
            right: 0;
        }

        .connection-point {
            width: 10px;
            height: 10px;
            background-color: red;
            position: relative;
        }

        ul li {
            margin: 10px;
            list-style-type: none;
        }

        .node-list {
            width: 150px;
        }
    </style>
</head>
<body>
<div id="app" style="display: flex">
    <div>
        <h3>可使用节点</h3>
        <ul>
            <!-- 遍历每个节点组 -->
            <li v-for="group in node_groups" :key="group.node_group">
                <h4>{{ group.node_group }}</h4>
                <ul class="node-list">
                    <!-- 遍历该组下的每个节点 -->
                    <li v-for="node in group.config" :key="node.id">
                        <button
                                :id="node.name"
                                @click="addRectangle(100, 100, node.width, node.height, node.name, node.input_points.length, node.output_points.length,node.items)"
                        >
                            {{ node.name }}
                        </button>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
    <div>
        <h1>可连接的矩形</h1>
        <div class="controls">
            <button id="clearAll" @click="clear_all_btn_click">清除所有</button>
            <button id="start" @click="start_btn_click">执行</button>
        </div>
        <div id="canvas">
            <svg id="connections"></svg>
        </div>
    </div>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            node_groups: [{group_name: '默认', config: [{name: '默认节点'}]}],
            nodes: [{name: ''}],
            canvas: null,
            rectangles: [],
            connections: [],
            draggedRect: null,
            offsetX: null, offsetY: null,
            selectedPoint: null,
            nextId: 1,
            connectionsSVG: null,
        },
        mounted() {
            this.get_nodes()
            this.canvas = document.getElementById('canvas');
            this.connectionsSVG = document.getElementById('connections');
            // 事件监听器
            canvas.addEventListener('mousedown', this.handleMouseDown);
            document.addEventListener('mousemove', this.handleMouseMove);
            document.addEventListener('mouseup', this.handleMouseUp);
            // 定期重绘连接线（处理窗口大小变化等）
            window.addEventListener('resize', this.redrawConnections);
        },
        methods: {
            clear_all_btn_click() {
                // 清除所有矩形
                this.rectangles.forEach(rect => rect.remove());
                this.rectangles = [];

                // 清除所有连接线
                this.connections.forEach(conn => {
                    const line = document.getElementById('connection-' + conn.id);
                    if (line) line.remove();
                });
                this.connections = [];

                this.nextId = 1;
            },
            start_btn_click() {
                console.log(this.node_groups)
                start_api({
                    rectangles: this.rectangles.map(rect => rect.id),
                    connections: this.connections,
                    items: this.node_groups.flatMap(group =>
                        group.config.flatMap(node => node.items || [])
                    ),
                    node_groups: this.node_groups
                }).then(res => {
                    console.log(res)
                })
            },
            async get_nodes() {
                nodes_api().then((res) => {
                        this.node_groups = res
                    }
                )
            },
            // 添加矩形
            addRectangle(x = 100, y = 100, width = 100, height = 100, title = '标题', leftPointQuantity = 3, rightPointQuantity = 3, items = []) {
                const rect = document.createElement('div');
                rect.className = 'rectangle';
                rect.id = 'rect-' + this.nextId++;
                rect.style.left = x + 'px';
                rect.style.top = y + 'px';
                rect.style.width = width + 'px';
                rect.style.height = height + 'px';
                canvas.appendChild(rect);

                // 添加删除按钮
                const deleteBtn = document.createElement('button');
                deleteBtn.className = 'delete-btn';
                deleteBtn.textContent = '×';
                deleteBtn.title = '删除矩形';
                deleteBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    this.deleteRectangle(rect);
                });
                rect.appendChild(deleteBtn)

                // 添加标题
                const h1 = document.createElement('div');
                h1.type = '';
                h1.textContent = title
                h1.className = 'title';
                rect.appendChild(h1);

                // 添加左侧连接点
                const leftPoints = document.createElement('div');
                leftPoints.className = 'left-points';
                for (let i = 0; i < leftPointQuantity; i++) {
                    const point = document.createElement('div');
                    point.className = 'connection-point point';
                    point.style.setProperty('--index', i);
                    point.dataset.rectId = rect.id;
                    point.dataset.side = 'left';
                    point.dataset.pointIndex = i;
                    point.addEventListener('click', this.handlePointClick);
                    leftPoints.appendChild(point);
                }
                rect.appendChild(leftPoints);

                // 添加右侧连接点
                const rightPoints = document.createElement('div');
                rightPoints.className = 'right-points';
                for (let i = 0; i < rightPointQuantity; i++) {
                    const point = document.createElement('div');
                    point.className = 'connection-point point';
                    point.style.setProperty('--index', i);
                    point.dataset.rectId = rect.id;
                    point.dataset.side = 'right';
                    point.dataset.pointIndex = i;
                    point.addEventListener('click', this.handlePointClick);
                    rightPoints.appendChild(point);
                }
                rect.appendChild(rightPoints);
                items.forEach(item => {
                    if (item.type === 'textarea') {
                        // 添加输入框
                        const inputBox = document.createElement('textarea');
                        inputBox.className = 'input-box';
                        rect.appendChild(inputBox);
                        // 绑定 input 事件，手动更新 Vue 数据
                        inputBox.addEventListener('input', (e) => {
                            item.result = e.target.value;
                        });
                    }

                    if (item.type === 'select') {
                        // 添加下拉框
                        const dropdown = document.createElement('select');
                        dropdown.className = 'dropdown';
                        // 示例选项
                        const options = ['Option 1', 'Option 2', 'Option 3'];
                        options.forEach(option => {
                            const optionElement = document.createElement('option');
                            optionElement.value = option;
                            optionElement.textContent = option;
                            dropdown.appendChild(optionElement);
                        });
                        rect.appendChild(dropdown);
                    }
                })

                this.rectangles.push(rect);
                return rect;
            },
            // 处理连接点点击
            handlePointClick(e) {
                const point = e.target;

                if (this.selectedPoint === null) {
                    // 第一次点击，选中连接点
                    this.selectedPoint = point;
                    point.style.backgroundColor = '#f1c40f';
                } else {
                    // 第二次点击，尝试连接
                    if (this.selectedPoint !== point &&
                        this.selectedPoint.dataset.rectId !== point.dataset.rectId) {

                        // 检查是否已经存在连接
                        const existingConnection = this.connections.find(conn =>
                            (conn.from.point === this.selectedPoint && conn.to.point === point) ||
                            (conn.from.point === point && conn.to.point === this.selectedPoint)
                        );

                        if (!existingConnection) {
                            // 创建新连接
                            this.createConnection(this.selectedPoint, point);
                        }
                    }

                    // 重置选中状态
                    this.selectedPoint.style.backgroundColor = '#e74c3c';
                    this.selectedPoint = null;
                }
            },

            // 创建连接
            createConnection(fromPoint, toPoint) {
                const connection = {
                    id: this.connections.length,
                    from: {
                        point: fromPoint,
                        rectId: fromPoint.dataset.rectId,
                        side: fromPoint.dataset.side,
                        index: fromPoint.dataset.pointIndex
                    },
                    to: {
                        point: toPoint,
                        rectId: toPoint.dataset.rectId,
                        side: toPoint.dataset.side,
                        index: toPoint.dataset.pointIndex
                    }
                };

                this.connections.push(connection);
                this.drawConnection(connection);
            },

            // 绘制连接线（使用曲线）
            drawConnection(connection) {
                const fromRect = document.getElementById(connection.from.rectId);
                const toRect = document.getElementById(connection.to.rectId);
                const fromPoint = connection.from.point;
                const toPoint = connection.to.point;

                // 获取连接点位置
                const fromRectRect = fromRect.getBoundingClientRect();
                const toRectRect = toRect.getBoundingClientRect();
                const fromPointRect = fromPoint.getBoundingClientRect();
                const toPointRect = toPoint.getBoundingClientRect();

                // 计算相对于画布的坐标
                const canvasRect = canvas.getBoundingClientRect();
                const fromX = fromPointRect.left + fromPointRect.width / 2 - canvasRect.left;
                const fromY = fromPointRect.top + fromPointRect.height / 2 - canvasRect.top;
                const toX = toPointRect.left + toPointRect.width / 2 - canvasRect.left;
                const toY = toPointRect.top + toPointRect.height / 2 - canvasRect.top;

                // 计算控制点（用于贝塞尔曲线）
                // 控制点的位置可以根据需要调整，这里使用简单的算法
                const dx = toX - fromX;
                const controlDistance = Math.abs(dx) * 0.6; // 控制点距离

                // 根据连接方向确定控制点
                let controlX1, controlY1, controlX2, controlY2;

                if (connection.from.side === 'right' && connection.to.side === 'left') {
                    // 从左到右的连接
                    controlX1 = fromX + controlDistance;
                    controlX2 = toX - controlDistance;
                } else if (connection.from.side === 'left' && connection.to.side === 'right') {
                    // 从右到左的连接
                    controlX1 = fromX - controlDistance;
                    controlX2 = toX + controlDistance;
                } else {
                    // 其他情况（如左右到左右或左到左）
                    controlX1 = fromX + controlDistance * (dx >= 0 ? 1 : -1);
                    controlX2 = toX - controlDistance * (dx >= 0 ? 1 : -1);
                }

                // Y方向的控制点，可以根据Y距离调整
                const dy = toY - fromY;
                const yControlFactor = 0.01; // Y方向控制点的强度
                controlY1 = fromY + dy * yControlFactor;
                controlY2 = toY - dy * yControlFactor;

                // 创建SVG路径数据 - 使用三次贝塞尔曲线
                const pathData = `M ${fromX} ${fromY} C ${controlX1} ${controlY1}, ${controlX2} ${controlY2}, ${toX} ${toY}`;

                // 创建或更新SVG路径
                let path = document.getElementById('connection-' + connection.id);
                if (!path) {
                    path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                    path.setAttribute('id', 'connection-' + connection.id);
                    path.setAttribute('fill', 'none');
                    path.setAttribute('stroke', '#2c3e50');
                    path.setAttribute('stroke-width', '2');
                    path.setAttribute('marker-end', 'url(#arrowhead)'); // 添加箭头（可选）
                    this.connectionsSVG.appendChild(path);
                }

                path.setAttribute('d', pathData);
            },

            // 删除矩形
            deleteRectangle(rect) {
                const rectId = rect.id;

                // 首先删除与该矩形相关的所有连接
                this.connections = this.connections.filter(conn => {
                    if (conn.from.rectId === rectId || conn.to.rectId === rectId) {
                        // 从SVG中移除连接线
                        const line = document.getElementById('connection-' + conn.id);
                        if (line) line.remove();
                        return false;
                    }
                    return true;
                });

                // 从数组中移除矩形
                this.rectangles = this.rectangles.filter(r => r !== rect);

                // 从DOM中移除矩形
                rect.remove();
            },

            // 重绘所有连接
            redrawConnections() {
                this.connections.forEach(connection => {
                    this.drawConnection(connection);
                });
            },

            // 鼠标按下事件（拖拽矩形）
            handleMouseDown(e) {
                const target = e.target;
                if (target.classList.contains('rectangle')) {
                    this.draggedRect = target;
                    const rect = this.draggedRect.getBoundingClientRect();
                    this.offsetX = e.clientX - rect.left;
                    this.offsetY = e.clientY - rect.top;

                    // 如果有选中的连接点，取消选中
                    if (this.selectedPoint) {
                        this.selectedPoint.style.backgroundColor = '#e74c3c';
                        this.selectedPoint = null;
                    }
                }
            },

            // 鼠标移动事件（拖拽矩形）
            handleMouseMove(e) {
                if (this.draggedRect) {
                    const canvasRect = canvas.getBoundingClientRect();
                    let left = e.clientX - canvasRect.left - this.offsetX;
                    let top = e.clientY - canvasRect.top - this.offsetY;

                    // 确保矩形在画布内
                    left = Math.max(0, Math.min(left, canvasRect.width - this.draggedRect.offsetWidth));
                    top = Math.max(0, Math.min(top, canvasRect.height - this.draggedRect.offsetHeight));

                    this.draggedRect.style.left = left + 'px';
                    this.draggedRect.style.top = top + 'px';

                    // 重绘所有连接线
                    this.redrawConnections();
                }
            },

            // 鼠标释放事件
            handleMouseUp() {
                this.draggedRect = null;
            },
        }
    });
</script>
</body>
</html>